#include "IP4Address.h"
#include "util/Convert.h"
#include "lang/StringFormat.hpp"
#include "array/Arrays.h"
using namespace yzrilyzr_lang;
using namespace yzrilyzr_util;
using namespace yzrilyzr_array;
namespace yzrilyzr_net{
	//std::shared_ptr<IP4Address> IP4Address::LOCAL_HOST=IP4Address::parse("127.0.0.1");
	//std::shared_ptr<IP4Address> IP4Address::ANY_ADDRESS=IP4Address::parse("0.0.0.0");
	
	IP4Address::IP4Address(const yzrilyzr_array::ByteArray & fromBytes) {
		fromByte(fromBytes);
	}
	IP4Address::IP4Address(int32_t maskLength, int32_t netAddr) : val(netAddr){
		this->maskLength=maskLength;
	}
	std::shared_ptr<IP4Address> IP4Address::parse(const String & str){
		std::shared_ptr<IP4Address> ipptr=std::make_shared<IP4Address>();
		IP4Address &ip=*ipptr;
		auto parts=str.split("/");
		auto octets=parts[0].split(".");
		if(octets.length!= 4){
			throw IllegalArgumentException("Invalid IPv4 address");
		}
		ip.val=0;
		for(int32_t i=0;i < 4;i++){
			int32_t octet=parseInt(octets[i]);
			if(octet < 0 || octet>255){
				throw IllegalArgumentException("Invalid IPv4 octet");
			}
			ip.val|=(octet << (24 - 8 * i));
		}
		if(parts.length > 1){
			ip.maskLength=parseInt(parts[1]);
			if(ip.maskLength < 0 || ip.maskLength>32){
				throw IllegalArgumentException("Invalid IPv4 mask length");
			}
		} else{
			ip.maskLength=32;
		}
		return ipptr;
	}
	int32_t IP4Address::hashCode()const{
		return Arrays::hashCode(val, maskLength);
	}
	bool IP4Address::operator==(const IP4Address & that)const{
		return val == that.val && maskLength == that.maskLength;
	}
	bool IP4Address::inRange(const IPAddress * targetRange)const {
		if(!IPAddress::isIPV4(targetRange)) return false;
		const IP4Address *target=static_cast<const IP4Address*>(targetRange);
		// 计算最小有效掩码长度
		int effectiveMask=Math::min(this->maskLength, target->maskLength);
		int mask=~((1 << (32 - effectiveMask)) - 1);
		return (this->val & mask) == (target->val & mask);
	}
	String IP4Address::toFullString()const {
		return toSimpleString() + (maskLength != 32?String("/") + maskLength:"");
	}
	String IP4Address::toMaskedString()const {
		int mask=~((1 << (32 - maskLength)) - 1);
		int netAddr=val & mask;
		return StringFormat::format("%d.%d.%d.%d", (netAddr >> 24) & 0xff, (netAddr >> 16) & 0xff, (netAddr >> 8) & 0xff,
							 netAddr &
							 0xff);
	}
	std::shared_ptr<IPAddress> IP4Address::toMasked(int32_t maskLength)const {
		int mask=~((1 << (32 - maskLength)) - 1);
		int netAddr=val & mask;
		return std::make_shared<IP4Address>(maskLength, netAddr);
	}
	std::shared_ptr<IPAddress> IP4Address::clone()const {
		auto a=toByte();
		return std::make_shared<IP4Address>(*a);
	}
	std::shared_ptr<ByteArray> IP4Address::toByte()const {
		std::shared_ptr<ByteArray> bptr=std::make_shared<ByteArray > (8);
		ByteArray & b=*bptr;
		b[0]=(int8_t)((val >> 24) & 0xff);
		b[1]=(int8_t)((val >> 16) & 0xff);
		b[2]=(int8_t)((val >> 8) & 0xff);
		b[3]=(int8_t)((val >> 0) & 0xff);
		b[4]=(int8_t)((maskLength >> 24) & 0xff);
		b[5]=(int8_t)((maskLength >> 16) & 0xff);
		b[6]=(int8_t)((maskLength >> 8) & 0xff);
		b[7]=(int8_t)((maskLength >> 0) & 0xff);
		return bptr;
	}
	void IP4Address::fromByte(const ByteArray & b){
		val=((b[0] & 0xff) << 24) | ((b[1] & 0xff) << 16) | ((b[2] & 0xff) << 8) | ((b[3] & 0xff));
		maskLength=((b[4] & 0xff) << 24) | ((b[5] & 0xff) << 16) | ((b[6] & 0xff) << 8) | ((b[7] & 0xff));
	}
	String IP4Address::toSimpleString()const {
		return StringFormat::format("%d.%d.%d.%d", (val >> 24) & 0xff, (val >> 16) & 0xff, (val >> 8) & 0xff, val & 0xff);
	}
	int IP4Address::getVersion()const{ return 4; }
}